package com.mall.user.handler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.mall.user.model.entity.Address;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 地址列表JSON类型处理器
 */
@Slf4j
@MappedTypes({List.class})
@MappedJdbcTypes({JdbcType.VARCHAR})
public class AddressListTypeHandler extends BaseTypeHandler<List<Address>> {

    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    static {
        // 注册JavaTimeModule以支持LocalDateTime等时间类型
        objectMapper.registerModule(new JavaTimeModule());
        // 配置时间序列化格式
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 忽略未知属性，避免反序列化失败
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 允许空字符串转为null
        objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<Address> parameter, JdbcType jdbcType) throws SQLException {
        try {
            String json = objectMapper.writeValueAsString(parameter);
            log.debug("序列化地址列表为JSON: {}", json);
            ps.setString(i, json);
        } catch (JsonProcessingException e) {
            log.error("将地址列表转换为JSON字符串时出错", e);
            throw new SQLException("将地址列表转换为JSON字符串时出错", e);
        }
    }

    @Override
    public List<Address> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return parseJson(json);
    }

    @Override
    public List<Address> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return parseJson(json);
    }

    @Override
    public List<Address> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return parseJson(json);
    }

    private List<Address> parseJson(String json) throws SQLException {
        if (json == null || json.trim().isEmpty()) {
            log.debug("地址JSON为空，返回空列表");
            return new ArrayList<>();
        }
        
        log.info("解析地址JSON: {}", json);
        
        try {
            List<Address> addresses = objectMapper.readValue(json, new TypeReference<List<Address>>() {});
            log.info("成功解析地址列表，数量: {}", addresses != null ? addresses.size() : 0);
            
            if (addresses != null) {
                for (int i = 0; i < addresses.size(); i++) {
                    Address addr = addresses.get(i);
                    log.info("地址[{}] - ID: {}, 姓名: {}, 电话: {}", i, addr.getId(), addr.getName(), addr.getPhone());
                }
            }
            
            return addresses != null ? addresses : new ArrayList<>();
        } catch (JsonProcessingException e) {
            log.error("解析JSON字符串为地址列表时出错，JSON: {}", json, e);
            throw new SQLException("解析JSON字符串为地址列表时出错", e);
        }
    }
}
